package procilege.compiler;

import procilege.impl.ComputationalEntityMgr;
import procilege.lang.BoolExprElement;
import procilege.lang.EntityExprElement;
import procilege.lang.ExprElement;
import procilege.lang.ExprSubstitute;
import procilege.lang.Name;
import procilege.lang.PredicateEntityProperty;
import procilege.lang.PredicateExpr;
import procilege.lang.PredicatePrivAvailiability;
import procilege.lang.PredicatePropertyExpr;
import procilege.lang.PrivExprComposition;
import procilege.lang.PrivExprElement;
import procilege.lang.PrivExprMergence;
import procilege.lang.RelationConformExpr;

import com.google.inject.Inject;

public class PalExprHelper {

	@Inject
	private ComputationalEntityMgr em;

	public PrivExprElement mergePrivilege(PrivExprElement a, PrivExprElement b) {

		PrivExprMergence m = null;

		if (a instanceof PrivExprMergence)
			m = (PrivExprMergence) a;

		else {
			m = new PrivExprMergence(null);
			m.mergePrivilege(a);
		}

		m.mergePrivilege(b);

		return m;
	}

	public PrivExprElement compose(PrivExprElement a, PrivExprElement b) {

		PrivExprComposition m = null;

		if (a instanceof PrivExprComposition)
			m = (PrivExprComposition) a;

		else {
			m = new PrivExprComposition();
			m.compose(a);
		}

		m.compose(b);

		return m;
	}

	public PrivExprElement mergeRestriction(PrivExprElement pe,
			BoolExprElement bool) {

		PrivExprMergence result = null;

		if (pe != null) {

			if (pe instanceof PrivExprMergence) {
				result = (PrivExprMergence) pe;
			} else {
				result = new PrivExprMergence(null);
				result.mergePrivilege(pe);
			}
		} else {
			result = new PrivExprMergence(null);
		}

		result.mergeRestriction(bool);

		return result;
	}

	public PrivExprElement mergeEntity(PrivExprElement pe, EntityExprElement ee) {

		PrivExprMergence result = null;

		if (pe instanceof PrivExprMergence) {
			result = (PrivExprMergence) pe;
		} else {
			result = new PrivExprMergence(null);
			result.mergePrivilege(pe);
		}

		result.mergeEntity(ee);

		return result;
	}

	public void setEntityCategory(Name element, Name category) {

		em.setIsA(element, category);
	}

	public void unsetEntityCategory(Name element, Name category) {

		em.setIsA(element, category);
	}

	public void defPrivilege(Name name, PrivExprElement pvexpr) {

		em.updatePrivlegeExpr(name, pvexpr);
	}

	public void defAssigment(PredicatePropertyExpr t, PredicateExpr v) {

		if (!(t instanceof PredicateEntityProperty)) {
			throw new UnsupportedOperationException("assignment: "
					+ t.getClass().getName());
		}

		PredicateEntityProperty pp = (PredicateEntityProperty) t;

		em.setEntityProperty(pp.getEntity(), pp.getProperty(), v);
	}

	public PrivExprElement privref(Name name) {

		return name;
	}

	public EntityExprElement entityname(Name name) {
		return name;
	}

	public PredicateExpr privavail(PrivExprElement pvexpr) {

		return new PredicatePrivAvailiability(pvexpr);
	}

	public ExprSubstitute substitute(ExprElement expr, ExprElement object,
			Name targetName) {

		ExprSubstitute subst = new ExprSubstitute(expr, object, targetName);

		return subst;
	}

	public PredicateExpr conform(PrivExprElement left, PrivExprElement right) {

		return new RelationConformExpr(left, right);
	}
}